﻿using System;
using System.Reflection;

namespace Moonlite.Data.Configuration
{
    /// <summary>
    /// Provides a spy over the current AppDomain's loaded assemblies.
    /// </summary>
    internal static class AssemblyLoadSpy
    {
        /// <summary>
        /// Loads the assembly configuration attachment.
        /// </summary>
        /// <param name="attachment">The attachment.</param>
        internal static void LoadAssemblyConfigurationAttachment(AssemblyConfigurationAttachment attachment)
        {
            if (attachment == null)
            {
                throw new ArgumentNullException("attachment");
            }

            attachment.ConfigurationInstance = ConfigurationManager.GetConfigurationInstanceForRegisteredAssembly(attachment.Assembly);
            ConfigurationManager.RaiseAssemblyLoadEvent(new ConfigurationAssemblyLoadEventArgs(attachment));
        }

        /// <summary>
        /// Loads the assembly.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        internal static void LoadAssembly(Assembly assembly)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }

            try
            {
                AssemblyConfigurationAttachment attachment = null;
                ConfigurationInstance instance = ConfigurationManager.GetConfigurationInstanceForRegisteredAssembly(assembly, out attachment);
                if (attachment != null)
                {
                    attachment.ConfigurationInstance = instance;
                    ConfigurationManager.RaiseAssemblyLoadEvent(new ConfigurationAssemblyLoadEventArgs(attachment));
                }
            }
            catch (InvalidOperationException)
            {
            }
        }

        /// <summary>
        /// Called when [assembly load].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.AssemblyLoadEventArgs"/> instance containing the event data.</param>
        private static void OnAssemblyLoad(object sender, AssemblyLoadEventArgs e)
        {
            if (e.LoadedAssembly != null)
            {
                LoadAssembly(e.LoadedAssembly);
            }
        }

        /// <summary>
        /// Initializes the <see cref="AssemblyLoadSpy"/> class.
        /// </summary>
        internal static void InitAssemblyLoadSpy()
        {
            AppDomain currentDomain = AppDomain.CurrentDomain;
            currentDomain.AssemblyLoad += OnAssemblyLoad;
        }
    }
}
